package com.cskaoyan.javase.io._8serialization;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * 序列化，将JVM堆内存中的对象二进制数据，直接输出写入到外存中进行持久化保存(文件,数据库)。
 * 反序列化，将外存中对象的二进制数据，读取进JVM内存，在堆上新建这个对象。
 *
 * 反序列化是一种全新的,独特的,不同以往学习过的,创建对象的方式,所以它具有学习的重要性
 * 创建对象的方式:
 *      1.new对象
 *      2.clone方法,本地方法创建一个和原先对象完全一致的独立新对象
 *      3.反序列化
 *
 * 具体来说序列化的过程,依赖于ObjectOutputStream
 * 首先它一定是一个字节输出流,它的作用是将一个JVM内存中的对象二进制数据写入到输出流当中(文件)
 *
 * 注意事项:
 *      1.如果对一个类的对象直接做序列号操作,就会抛出异常NotSerializableException
 *      某个类的对象若想进行序列化操作，必须实现接口java.io.Serializable，该接口是一个空接口，是一个标记接口。实现该接口的类意味着对象能够进行序列化/反序列化操作。这一点和之前clone方法的Cloneable接口是一致的。
 *
 *      2.序列化得到的数据是对象的二进制字节数据,人肉眼是不能看明白的
 *      这时还需要对应的对象字节输入流来读取这个数据,并且将这个持久化保持的对象还原
 *
 * @since 11:15
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) throws IOException {
        // ObjectOutputStream(OutputStream out)	创建写入指定 OutputStream 的 ObjectOutputStream。
        ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream("a.txt"));
        Student s = new Student(18, "张三", "男");
        objOut.writeObject(s);
        // void	writeObject(Object obj)	将指定的对象写入 ObjectOutputStream序列化流
        objOut.flush();
        objOut.close();
    }
}

class Student implements Serializable {
    private int age;
    private String name;
    private String gender;
    private double score;
    private static final long serialVersionUID = 1000;

    public Student(int age, String name, String gender) {
        this.age = age;
        this.name = name;
        this.gender = gender;
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("Student{");
        sb.append("age=").append(age);
        sb.append(", name='").append(name).append('\'');
        sb.append(", gender='").append(gender).append('\'');
        sb.append(", score=").append(score);
        sb.append('}');
        return sb.toString();
    }
}